package com.danbay.cloud.account.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.danbay.cloud.account.client.SmsServiceClient;
import com.danbay.cloud.account.config.AccountProperties;
import com.danbay.cloud.account.dto.AccountDto;
import com.danbay.cloud.account.dto.EmployeeDto;
import com.danbay.cloud.account.dto.EmployeeInfoDto;
import com.danbay.cloud.account.dto.EnterpriseInfoDto;
import com.danbay.cloud.account.entity.Account;
import com.danbay.cloud.account.entity.AccountRole;
import com.danbay.cloud.account.entity.Employee;
import com.danbay.cloud.account.entity.Enterprise;
import com.danbay.cloud.account.mapper.AccountMapper;
import com.danbay.cloud.account.mapper.AccountRoleMapper;
import com.danbay.cloud.account.mapper.EmployeeMapper;
import com.danbay.cloud.account.mapper.EnterpriseMapper;
import com.danbay.cloud.account.service.api.IEmployeeService;
import com.danbay.cloud.base.constants.Roles;
import com.danbay.cloud.common.api.dto.sms.EmployeeRegNoticeDto;
import com.danbay.framework.db.pagination.PageParam;
import com.danbay.framework.db.pagination.PageQuery;
import com.danbay.framework.db.pagination.PageResult;
import com.danbay.framework.db.pagination.PagingHelper;
import com.danbay.framework.exception.BusinessException;
import com.danbay.framework.utils.BeanUtils;
import com.danbay.framework.utils.BeanValidator;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

/**
 * @author SJG
 *         2018/1/4.
 */
@Service
public class EmployeeService implements IEmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private EnterpriseMapper enterpriseMapper;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountRoleMapper accountRoleMapper;
    @Autowired
    private AccountProperties accountProperties;

    @Autowired
    private AccountService accountService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private SmsServiceClient smsServiceClient;

    /**
     * 分页查询企业下员工信息
     *
     * @param param 查询参数
     * @return 员工列表
     */
    @Override
    public PageResult<EmployeeInfoDto> findByPage(PageParam<EmployeeInfoDto> param) {
        return PagingHelper.pageQuery(param, EmployeeInfoDto.class, Employee.class,
                (PageQuery<Employee, Employee>) (page1, param1) -> employeeMapper.findEmployees(page1, param1));
    }

    /**
     * 取员工信息
     *
     * @param eid 员工id
     * @return 员工信息
     */
    @Override
    public EmployeeInfoDto get(Integer eid) throws BusinessException {
        Employee employee = checkNotExist(eid);
        EmployeeInfoDto employeeInfoDto = BeanUtils.convert(employee, EmployeeInfoDto.class);
        //取企业账户组
        EnterpriseInfoDto enterpriseInfoDto = enterpriseService.get(employee.getEnterpriseId());
        if (enterpriseInfoDto != null) {
            employeeInfoDto.setAccountGroup(enterpriseInfoDto.getAccountGroupId());
        }
        return employeeInfoDto;
    }

    /**
     * 添加员工信息
     * 添加员工后会生成员工账户，再设置员工账户的权限
     *
     * @param employee 员工信息
     * @throws BusinessException 业务异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(EmployeeDto employee) throws BusinessException {
        BeanValidator.valid(employee);
        checkPhoneNumExists(employee.getEnterpriseId(), employee.getPhoneNum());

        Enterprise enterprise = enterpriseMapper.selectById(employee.getEnterpriseId());
        if (enterprise == null) {
            throw new BusinessException("所属企业不存在");
        }
        String accountId = employee.getPhoneNum();
        Account account = accountMapper.selectById(accountId);
        //账户不存在才需要生成账户
        if (account == null) {
            //生成员工账户
            accountService.addAccount(AccountDto.builder()
                    .userName(accountId)
                    .phoneNum(employee.getPhoneNum())
                    .accountGroup(enterprise.getAccountGroupId())
                    .nickName(employee.getName())
                    .build());
            //设置账户角色
            accountRoleMapper.insert(AccountRole.builder()
                    .userName(accountId)
                    .roleName(Roles.EMPLOYEE.roleName())
                    .build());
        } else {
            //添加账户角色
            Set<String> accountRoles = accountService.getAccountRoles(accountId);
            if (!accountRoles.contains(Roles.EMPLOYEE.roleName())) {
                accountRoleMapper.insert(AccountRole.builder()
                        .userName(accountId)
                        .roleName(Roles.EMPLOYEE.roleName())
                        .build());
            }
            //更新账户组
            String groupId = enterprise.getAccountGroupId() + ",";
            if (!account.getGroupIds().contains(groupId)) {
                account.setGroupIds(account.getGroupIds() + groupId);
                accountMapper.updateById(account);
            }
        }
        //添加员工信息
        employeeMapper.insert(Employee.builder()
                .name(employee.getName())
                .phoneNum(employee.getPhoneNum())
                .enterpriseId(employee.getEnterpriseId())
                .bindAccount(accountId)
                .freeze(false)
                .del(false)
                .addTime(DateTime.now().toDate()).build()
        );
    }

    /**
     * 检查员工电话号码是否存在
     *
     * @param eid      员工所在企业id
     * @param phoneNum 员工电话号码
     * @throws BusinessException 业务异常
     */
    @Override
    public void checkPhoneNumExists(Integer eid, String phoneNum) throws BusinessException {
        if (employeeMapper.selectCount(new EntityWrapper<>(Employee.builder().enterpriseId(eid).phoneNum(phoneNum).build())) > 0) {
            throw new BusinessException("员工在该企业的电话号码已存在");
        }
    }

    /**
     * 员工账户注册成功后,发送注册短信
     *
     * @param mobile 员工账户电话
     * @param name   企业名
     */
    @Override
    public void sendRegMessage(String mobile, String name) throws BusinessException {
        smsServiceClient.sendEmployeeRegNotice(
                EmployeeRegNoticeDto.builder()
                        .name(name)
                        .tel(mobile)
                        .pwd(accountProperties.getDefaultPassword())
                        .build());
    }

    /**
     * 冻结员工
     * 登录时要判断账户所在账户组的企业中的员工是否已冻结
     *
     * @param eid 员工id
     * @throws BusinessException 业务异常
     */
    @Override
    public void freeze(Integer eid) throws BusinessException {
        int r = employeeMapper.updateById(Employee.builder().id(eid).freeze(true).build());
        if (r == 0) {
            throw new BusinessException("冻结员工失败");
        }
    }

    /**
     * 解冻员工
     *
     * @param eid 员工id
     * @throws BusinessException 业务异常
     */
    @Override
    public void unfreeze(Integer eid) throws BusinessException {
        int r = employeeMapper.updateById(Employee.builder().id(eid).freeze(false).build());
        if (r == 0) {
            throw new BusinessException("解冻员工失败");
        }
    }

    /**
     * 删除员工
     * 1.删除员工信息,2.取消员工账户所在企业组
     *
     * @param eid 员工id
     * @throws BusinessException 业务异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer eid) throws BusinessException {
        Employee employee = checkNotExist(eid);
        employeeMapper.deleteById(eid);
        Enterprise enterprise = enterpriseMapper.selectById(employee.getEnterpriseId());
        if (enterprise == null) {
            return;
        }
        //解除与企业账户组绑定
        accountService.cancelGroup(employee.getBindAccount(), enterprise.getAccountGroupId());
    }

    /**
     * 检查员工是否存在
     *
     * @param eid 员工id
     * @throws BusinessException 业务异常
     */
    private Employee checkNotExist(Integer eid) throws BusinessException {
        if (eid == null) {
            throw new BusinessException("该员工不存在");
        }
        Employee employee = employeeMapper.selectById(eid);
        if (employee == null) {
            throw new BusinessException("该员工不存在");
        }
        return employee;
    }
}
